package bl;

import java.math.BigInteger;
import java.security.InvalidParameterException;

public class IntegersVEBToken implements VEBTokenI {

	public BigInteger EBtoken;
	private BigInteger token;

	public IntegersVEBToken(BigInteger veb, BigInteger eb) {
		this.token = veb;
		this.EBtoken = eb;
	}

	public IntegersVEBToken(byte[] bytes, IntegersPublicParameters ipp) {
		this.EBtoken = null;
		this.token = new BigInteger(bytes);
		if (this.token.compareTo(BigInteger.ZERO) < 0
				|| this.token.compareTo(ipp.G) >= 0) {
			this.token = null;
			throw new InvalidParameterException(
					"Token value must be between 0 to the group order");
		}
	}

	public BigInteger CalculateH(BigInteger bi, IntegersPublicParameters ipp)
			throws IneligibleTypeException {
		return new BigInteger(Common.SHA256(Common.concat(this.getBytes(ipp),
				bi.toByteArray())));
	}

	@Override
	public boolean Verify(NIZKproofI p, PublicParametersI pp)
			throws IneligibleTypeException {
		if (!(pp instanceof IntegersPublicParameters)
				|| !(p instanceof IntegersNIZKproof)) {
			throw new IneligibleTypeException();
		}

		IntegersNIZKproof proof = (IntegersNIZKproof) p;
		IntegersPublicParameters ipp = (IntegersPublicParameters) pp;

		BigInteger p1 = proof.p1;
		BigInteger p2 = proof.p2;

		// VERIFICATION GOES HERE
		BigInteger h = this.CalculateH(p1, ipp);
		BigInteger val1 = ipp.g.modPow(p2, ipp.G);
		BigInteger val2 = (this.token.modPow(h, ipp.G)).multiply(p1).mod(ipp.G);

		return val1.compareTo(val2) == 0;
	}

	@Override
	public byte[] getBytes(PublicParametersI ipp)
			throws IneligibleTypeException {
		if (!(ipp instanceof IntegersPublicParameters)) {
			throw new IneligibleTypeException();
		}

		return Common.CreatePaddedBigIntegerBytes(this.token,
				((IntegersPublicParameters) ipp).GetTokenLengthBytes());
	}

	@Override
	public boolean Compare(VEBTokenI t2) throws IneligibleTypeException {
		if (!(t2 instanceof IntegersVEBToken)) {
			throw new IneligibleTypeException();
		}

		return this.token.compareTo(((IntegersVEBToken) t2).token) == 0;
	}
}
